package com.codeoss.module.stock.service.impl;

import java.math.BigDecimal;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.codeoss.framework.service.impl.BaseService;
import com.codeoss.framework.util.DateUtil;
import com.codeoss.module.ir.service.IIrDocTypeService;
import com.codeoss.module.ir.service.IIrSequenceService;
import com.codeoss.module.sale.model.SaleOrder;
import com.codeoss.module.sale.model.SaleOrderLine;
import com.codeoss.module.sale.service.ISaleOrderLineService;
import com.codeoss.module.sale.service.ISaleOrderService;
import com.codeoss.module.stock.dao.StockOutMapper;
import com.codeoss.module.stock.model.StockOut;
import com.codeoss.module.stock.model.StockOutConfirm;
import com.codeoss.module.stock.model.StockOutLine;
import com.codeoss.module.stock.model.StockOutLineMa;
import com.codeoss.module.stock.model.StockStorage;
import com.codeoss.module.stock.model.StockTransaction;
import com.codeoss.module.stock.service.IStockLocatorService;
import com.codeoss.module.stock.service.IStockOutConfirmService;
import com.codeoss.module.stock.service.IStockOutLineMaService;
import com.codeoss.module.stock.service.IStockOutLineService;
import com.codeoss.module.stock.service.IStockOutService;
import com.codeoss.module.stock.service.IStockStorageService;
import com.codeoss.module.stock.service.IStockTransactionService;

@Service
public class StockOutService extends BaseService<StockOutMapper, StockOut> implements IStockOutService {
	@Autowired
	private ISaleOrderService saleOrderService;
	@Autowired
	private DateUtil dateUtil;
	@Autowired
	private IIrDocTypeService irDocTypeService;
	@Autowired
	private IIrSequenceService irSequenceService;
	@Autowired
	private ISaleOrderLineService saleOrderLineService;
	@Autowired
	private IStockLocatorService stockLocatorService;
	@Autowired
	private IStockOutLineService stockOutLineService;
	@Autowired
	private IStockOutConfirmService stockOutConfirmService;
	@Autowired
	private IStockOutLineMaService stockOutLineMaService;
	@Autowired
	private IStockStorageService stockStorageService;
	@Autowired
	private IStockTransactionService stockTransactionService;
	@Override
	@Transactional
	public StockOut generateStockOut(Long saleOrderId) {
		// TODO Auto-generated method stub
		StockOut stockOut=new StockOut();
		SaleOrder saleOrder=saleOrderService.getById(saleOrderId);
		String docStatus=saleOrder.getDocStatus();
		if(!"CO".equals(docStatus)) {
			throw new RuntimeException("请先完成单据");
		}
		stockOut.setSaleOrderId(saleOrderId);
		stockOut.setMovementDate(dateUtil.getSqlNowDatetime());
		Long docTypeId=irDocTypeService.getIrDocTypeIdByCode("stockout");
		stockOut.setIrDocTypeId(docTypeId);
		stockOut.setStockWarehouseId(saleOrder.getStockWarehouseId());
		stockOut.setDocStatus("DR");
		stockOut.setResPartnerId(saleOrder.getResPartnerId());
		stockOut.setResUserId(saleOrder.getResUserId());
		stockOut.setResPartnerLocationId(saleOrder.getResPartnerLocationId());
		stockOut.setDocumentNo(irSequenceService.getNextSequenceNo("stockout"));
		insert(stockOut);
		
		List<SaleOrderLine> saleOrderLineList=saleOrderLineService.getLineListBySaleOrderId(saleOrderId);
		int lineNo=10;
		Long defaultLocatorId=stockLocatorService.getDefaultLocator(saleOrder.getStockWarehouseId()).getId();
		for(SaleOrderLine saleOrderLine:saleOrderLineList) {
			StockOutLine stockOutLine=new StockOutLine();
			stockOutLine.setSaleOrderLineId(saleOrderLine.getId());
			stockOutLine.setLine(lineNo);
			stockOutLine.setProductProductId(saleOrderLine.getProductProductId());
			stockOutLine.setProductAttrSetInstanceId(saleOrderLine.getProductAttrSetInstanceId());
			stockOutLine.setUomUomId(saleOrderLine.getUomUomId());
			stockOutLine.setStockLocatorId(defaultLocatorId);
			stockOutLine.setQtyEntered(saleOrderLine.getQtyEntered());
			stockOutLine.setStockOutId(stockOut.getId());
			lineNo+=10;
			stockOutLineService.insert(stockOutLine);
		}
		return stockOut;
	}
	@Override
	@Transactional
	public void prepareIt(Long id) {
		// TODO Auto-generated method stub
		List<StockOutLine> stockOutLineList=stockOutLineService.getLineListByStockOutId(id);
		if(stockOutLineList==null ||stockOutLineList.size()==0 ) {
			throw new RuntimeException("没有行明细");
		}
		
		List<StockOutConfirm> confirmList=stockOutConfirmService.getConfirmByStockOutId(id);
		for(int i=0;i<confirmList.size();i++) {
			StockOutConfirm stockOutConfirm=confirmList.get(i);
			if(!"CO".equals(stockOutConfirm.getDocStatus())) {
				throw new RuntimeException("请先完成出库确认单");
			}
		}
	}
	@Override
	@Transactional
	public void completeIt(Long id) {
		// TODO Auto-generated method stub
		StockOut stockOut=getById(id);
		stockOut.setDocStatus("CO");
		update(stockOut);
		if(!stockOut.getApproved()) {
			return;
		}
		List<StockOutLine> stockOutLineList=stockOutLineService.getLineListByStockOutId(id);
		for(int i=0;i<stockOutLineList.size();i++) {
			StockOutLine stockOutLine=stockOutLineList.get(i);
			checkMaterialPolicy(stockOut,stockOutLine);
			if(stockOutLine.getProductAttrSetInstanceId()==null) {
				QueryWrapper<StockOutLineMa> mAQuery=new QueryWrapper<StockOutLineMa>();
				mAQuery.eq("stock_out_line_id", stockOutLine.getId());
				List<StockOutLineMa> stockOutLineMaList=stockOutLineMaService.list(mAQuery);
				for(int j=0;j<stockOutLineMaList.size();j++) {
					StockOutLineMa stockOutLineMa=stockOutLineMaList.get(j);
					stockStorageService.add(stockOut.getStockWarehouseId(), stockOutLine.getStockLocatorId(), 
							stockOutLine.getProductProductId(), stockOutLineMa.getProductAttrSetInstanceId(), stockOutLineMa.getMovementQty().negate(),null, null);
				}
			}else {
				BigDecimal movementQty=stockOutLine.getMovementQty();
				stockStorageService.add(stockOut.getStockWarehouseId(), stockOutLine.getStockLocatorId(), 
						stockOutLine.getProductProductId(), stockOutLine.getProductAttrSetInstanceId(), movementQty.negate(),null, null);
			}
			BigDecimal movementQty=stockOutLine.getMovementQty();
			Long saleOrderLineId=stockOutLine.getSaleOrderLineId();
			if(saleOrderLineId!=null) {
				SaleOrderLine saleOrderLine=saleOrderLineService.getById(saleOrderLineId);
				BigDecimal qtyReserved=saleOrderLine.getQtyReserved();
				if(qtyReserved==null) {
					qtyReserved=new BigDecimal(0);
				}
				qtyReserved=qtyReserved.subtract(movementQty);
				saleOrderLine.setQtyReserved(qtyReserved);
				
				BigDecimal qtyDelivered=saleOrderLine.getQtyDelivered();
				if(qtyDelivered==null) {
					qtyDelivered=new BigDecimal(0);
				}
				qtyDelivered=qtyDelivered.add(movementQty);
				saleOrderLine.setQtyDelivered(qtyDelivered);
				saleOrderLineService.update(saleOrderLine);
				
				stockStorageService.add(stockOut.getStockWarehouseId(), stockOutLine.getStockLocatorId(), 
						stockOutLine.getProductProductId(), saleOrderLine.getProductAttrSetInstanceId(),null, movementQty.negate(), null);
			}
			StockTransaction stockTransaction=new StockTransaction();
			String movementType="stockout";
			stockTransaction.setProductProductId(stockOutLine.getProductProductId());
			stockTransaction.setStockLocatorId(stockOutLine.getStockLocatorId());
			stockTransaction.setProductAttrSetInstanceId(stockOutLine.getProductAttrSetInstanceId());
			stockTransaction.setMovementDate(stockOut.getMovementDate());
			stockTransaction.setMovementQty(movementQty);
			stockTransaction.setMovementType(movementType);
			stockTransaction.setStockOutLineId(stockOutLine.getId());
			stockTransactionService.insert(stockTransaction);
		}
	}
	
	@Transactional
	private void checkMaterialPolicy(StockOut stockOut,StockOutLine line) {
		QueryWrapper<StockOutLineMa> query=new QueryWrapper<StockOutLineMa>();
		query.eq("stock_out_line_id", line.getId());
		stockOutLineMaService.remove(query);
		
		if(line.getProductAttrSetInstanceId()==null) {
			 List<StockStorage> stockStorageList=stockStorageService.getAvailableStockStorageList(line.getProductProductId(), line.getStockLocatorId());
			 BigDecimal qtyToDeliver = line.getMovementQty();
				for (StockStorage storage: stockStorageList)
				{
					if (storage.getQtyOnhand().compareTo(qtyToDeliver) >= 0)
					{
					    StockOutLineMa ma = new StockOutLineMa();;
					    ma.setStockOutLineId(line.getId());
					    ma.setProductAttrSetInstanceId(storage.getProductAttrSetInstanceId());
					    ma.setMovementQty(qtyToDeliver);
						stockOutLineMaService.insert(ma);
						qtyToDeliver = new BigDecimal(0);
					}
					else
					{
						StockOutLineMa ma = new StockOutLineMa();;
					    ma.setStockOutLineId(line.getId());
					    ma.setProductAttrSetInstanceId(storage.getProductAttrSetInstanceId());
					    ma.setMovementQty(storage.getQtyOnhand());
						stockOutLineMaService.insert(ma);
						qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnhand());
					}

					if (qtyToDeliver.signum() == 0)
						break;
				}

				if (qtyToDeliver.signum() != 0)
				{
					StockOutLineMa ma = new StockOutLineMa();;
				    ma.setStockOutLineId(line.getId());
				    ma.setMovementQty(qtyToDeliver);
					stockOutLineMaService.insert(ma);
				}
		}
	}
	
	@Override
	@Transactional
	public void approveIt(Long id) {
		// TODO Auto-generated method stub
		StockOut stockOut=getById(id);
		stockOut.setApproved(true);
		update(stockOut);
	}
	
	
	@Override
	@Transactional
	public void rejectIt(Long id) {
		// TODO Auto-generated method stub
		StockOut stockOut=getById(id);
		stockOut.setApproved(false);
		update(stockOut);
	}
	
	
	@Override
	@Transactional
	public void setDocStatus(Long id, String docStatus) {
		// TODO Auto-generated method stub
		StockOut stockOut=getById(id);
		stockOut.setDocStatus(docStatus);
		update(stockOut);
	}
}